package com.share.mail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Message.RecipientType;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.servlet.ServletContext;

import org.springframework.stereotype.Component;

import com.share.commons.freemarker.FreeMarkerToMailTemplateUtil;
import com.share.commons.util.ValidateEmail;
import com.share.commons.util.WebSiteUrl;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;

/**
 * 说明：邮件发送
 * <br/>作者：杨浩泉
 * <br/>日期：2009-9-5
 */
@Component
public class SendMailManager {
	
	/**
	 * 邮件发送
	 * @param mailinfo 待发送的信息
	 */
	public boolean sendMailMessages(MailInfoVO mailinfo,ServletContext sc) {
		
		if(null != mailinfo) {
			//获得MailSMTP的缺省配置信息
			MailConfiguraton config = MailConfiguraton.getInstance() ;
			try {
				//设置邮件的发送协议
				Properties pros = System.getProperties() ;
				pros.setProperty("mail.smtp.host", config.getMailSMTPHost()) ;
				pros.setProperty("mail.smtp.port", config.getMailSMTPPort()) ;
				pros.setProperty("mail.smtp.auth", config.getMailAuth()) ;
				
				String userName = (null != mailinfo.getUsername() && !"".equals(mailinfo.getUsername().trim()) ? mailinfo.getUsername().trim() : config.getUserNameAdmin()) ;
				String passWord = (null != mailinfo.getPassword() && !"".equals(mailinfo.getPassword().trim()) ? mailinfo.getPassword().trim() : config.getUserNameAdmin()) ;
				String mailFrom = (null != mailinfo.getFromAddr() && !"".equals(mailinfo.getFromAddr()) ? mailinfo.getFromAddr():config.getUserNameAdmin()) ;
				
				//如果发件人地址为空，则以管理员的地址发送
				if(null == mailinfo.getFromAddr() || mailinfo.getFromAddr().trim().equals("")) {
					userName = config.getUserNameAdmin() ;
					passWord = config.getPassWordAdmin() ;
				}
				
				//设置邮件发送的类型
				String mimeType = (mailinfo.getContentType().trim().equals("")?MailTypeEnum.HTML.getType():MailTypeEnum.TEXT.getType()) +"; charset=UTF-8" ;
				//指定邮件优先级
				String priority =  (mailinfo.getPriority().trim().equals("URG")?MailPriorityEnum.URG.getName():MailPriorityEnum.NORMAL.getName()) ;
				
				//获得邮件内容
				String mailCtx = mailinfo.getContent() ;
				//判断是否使用模板
				mailCtx = (null == mailinfo.getTemplateFileName() || "".equals(mailinfo.getTemplateFileName())?mailCtx:loadingMailTemplate(sc,mailinfo)) ;
				//如果是纯文本类型，则去除所有的HTML标签代码
				if(mailinfo.getContentType().equals("text/plain")) {
					mailCtx = WebSiteUrl.HtmltoText(mailCtx) ;
				}
				
				//System.out.println("--" + userName + "---" + passWord + "---" + mailFrom + "===>" + mailinfo.getRecipientTO());
				
				//获取基于Properties Session会话对象，并通过MyAuthenticator类来创建一个账号密码验证器
				Session session = Session.getInstance(pros,new MyAuthenticator(userName,passWord)) ;
				//session.setDebug(true) ;
				
				//从Session创建一个MimeMessage对象
				Message msg = new MimeMessage(session) ;
	
				//设置发件人的地址，以及别名，并进行编码
				msg.setFrom(new InternetAddress(mailFrom,MimeUtility.encodeWord(mailinfo.getAliasName(),"UTF-8","Q"))) ;
				
				//设置收件人和抄送以及密送人地址
				setRecipient(mailinfo,msg) ;
	
				//指定邮件优先级 1:紧急 3:普通 5:缓慢
				msg.setHeader("X-Priority", priority);
				
				//设置邮件主题，并进行编码
				msg.setSubject(mailinfo.getSubject()) ;
				
				//设置邮件发送日期
				msg.setSentDate(new Date()) ;
				
				//Multipart作为信息载体的容器，将MimeBodyPart添加到Multipart对象中
				Multipart mp = new MimeMultipart() ;
				
				//MimeBodyPart对象做为信息的载体，MimeBodyPart被认为有两部分
				MimeBodyPart mb1 = new MimeBodyPart() ;
				
				//第一部分为普通信息的载体，并设置MIME类型为text/plain或text/html、multipart/mixed
				mb1.setContent(mailCtx, mimeType) ;
				
				//将第一部分添加到Multipart容器中
				mp.addBodyPart(mb1) ;
				
				//是否有附件，附件信息作为MimeBodyPart的第二部分
				if(null != mailinfo.getAttachFileNames() && mailinfo.getAttachFileNames().length > 0) {
					//设置附件，发送单个附件
					//mb2.attachFile("d:\\互联网新闻开放协议.txt") ;
					//mb2.setFileName(MimeUtility.encodeText("互联网新闻开放协议","UTF-8", "B")) ;
					
					for(int i=0; i<mailinfo.getAttachFileNames().length; i++) {
						//如果该邮件带有附件，需创建第二个MimeBodyPart对象，用来做附件的载体
						MimeBodyPart mb2 = new MimeBodyPart() ;
						
						// 获得附件
						DataSource source = new FileDataSource(mailinfo.getAttachFileNames()[i]) ;
						//设置附件的数据处理器
						mb2.setDataHandler(new DataHandler(source)) ;
						
						// 设置附件文件名
						mb2.setFileName(MimeUtility.encodeText(source.getName(),"UTF-8","B")) ;
						
						//加入第二部分到容器中
						mp.addBodyPart(mb2) ;
					}
				}
				
				//将Multipart对象设置到Message中进行发送
				msg.setContent(mp) ;
				
				//通过Transport对象来 发送邮件
				Transport.send(msg) ;
				
				System.out.println("-------From:"+mailFrom+"-------邮件发送成功--------To:"+mailinfo.getRecipientTO()+"-------");
				return true ;
			} catch (AddressException e) {
				e.printStackTrace();
			} catch (NoSuchProviderException e) {
				e.printStackTrace();
			} catch (MessagingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false ;
	}
	
	/**
	 * 设置收件人和抄送以及密送人地址
	 * @param mailinfo
	 * @param msg
	 * @throws MessagingException
	 */
	public void setRecipient(MailInfoVO mailinfo,Message msg) throws MessagingException {
		if(null != mailinfo.getRecipientTO() && !"".equals(mailinfo.getRecipientTO())) {
			//获取所有收件人地址
			List<InternetAddress> list = recipientAddress(mailinfo.getRecipientTO()) ;
			System.out.println("所有收件人地址："+list);
			//设置可以群发和单发收件人
			InternetAddress[] toAddress = (InternetAddress[])list.toArray(new InternetAddress[list.size()]) ;
			//设置收件人地址
			msg.addRecipients(RecipientType.TO, toAddress) ;
		}
		if(null != mailinfo.getRecipientCC() && !"".equals(mailinfo.getRecipientCC())) {
			//获取所有抄送人地址
			List<InternetAddress> list = recipientAddress(mailinfo.getRecipientCC()) ;
			System.out.println("所有抄送人地址："+list);
			//设置可以群发和单发抄送人
			InternetAddress[] ccAddress = (InternetAddress[])list.toArray(new InternetAddress[list.size()]) ;
			//设置抄送人地址
			msg.addRecipients(RecipientType.CC, ccAddress) ;
		}
		if(null != mailinfo.getRecipientBCC() && !"".equals(mailinfo.getRecipientBCC())) {
			//获取所有暗送人地址
			List<InternetAddress> list = recipientAddress(mailinfo.getRecipientBCC()) ;
			System.out.println("所有暗送人地址："+list);
			//设置可以群发和单发暗送人
			InternetAddress[] bccAddress = (InternetAddress[])list.toArray(new InternetAddress[list.size()]) ;
			//设置暗送人的地址
			msg.addRecipients(RecipientType.BCC, bccAddress) ;
		}
	}
	
	/**
	 * 解析群发或单发的邮箱地址
	 * @param toAddr 待解析的邮箱地址，多个邮箱地址以","分隔
	 * @return 集合List<InternetAddress>
	 */
	public static List<InternetAddress> recipientAddress(String toAddr) {
		List<InternetAddress> list = new ArrayList<InternetAddress>() ;
		String[] to = toAddr.split(",") ;
		
		for(int i=0; i<to.length; i++) {
			try {
				if(!"".equals(to[i]) && ValidateEmail.checkMail(to[i])) {
					list.add(new InternetAddress(to[i])) ;
				} else {
					System.out.println("【出错==》邮箱地址不符合标准，请检查...】");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return list ;
	}
	
	/**
	 * 加载模板文件
	 * @param sc ServletContext
	 * @param mailinfo 相关数据
	 * @return String
	 */
	public String loadingMailTemplate(ServletContext sc,MailInfoVO mailinfo) {
		Map<String,String> model = new HashMap<String,String>() ;
		model.put("something",mailinfo.getContent()) ;
		
		return FreeMarkerToMailTemplateUtil.MailTemplateToString(sc, mailinfo.getTemplateFileName(), model) ;
	}
	
	
	public static void main(String[] args) {
		
		String form = "serup_server@126.com" ;
		String to = "serupabc@126.com,serup_server@126.com" ;
		String bcc = "yhqsaber@126.com" ;
		
		MailInfoVO mailinfo = new MailInfoVO() ;
		mailinfo.setAliasName("孤独的狼") ;
		mailinfo.setUsername("serup_server") ;
		mailinfo.setPassword("serup_server123") ;
		mailinfo.setFromAddr(form) ;
		mailinfo.setSubject("hello————Test") ;
		mailinfo.setContent("<h1>AAA</h1><img src='cid:d:\1212.gif'/>") ;
		mailinfo.setRecipientTO(to) ;
		mailinfo.setRecipientBCC(bcc) ;
		//mailinfo.setContentType("text/plain") ;
		mailinfo.setPriority(MailPriorityEnum.URG.getName()) ;
		
		mailinfo.setAttachFileNames(new String[]{"c:\\email.txt","d:\\互联网新闻开放协议.txt"}) ;
		
		new SendMailManager().sendMailMessages(mailinfo,null) ;
	}
	
	
}
